#继承
'''
继承是一种类间的关系，描述一个类从另一个类获取成员信息的类间关系。
继承必定发生在连个类之间，参与继承关系的双方成为父类和子类。

'''
#继承的特点
'''
继承可以使得子类具有父类的各种属性和方法，而不需要再次写向相同的代码。

如果一个类A的属性和发放可以复用，则可以通过继承传递给类B。
此时A为父类，B为子类。
'''
#继承的优点：
'''
1.减少了重复代码；
2.增加了类的耦合性（模块间的关联程度）；
3.使得代码更加的规范化、合理化。
'''
#继承的格式
'''
class 类名（父类名）：
    pass    #什么执行语句都没有，可以写pass
'''
#例子1：不是使用继承的代码
class Person:
    def sing(self):
        print('唱歌')

    def dance(self):
        print('跳舞')

p = Person()
p.sing()
p.dance()
print('\n')


#例子2：使用继承的代码
class God:
    def sing(self):
        print('唱歌唱歌')

    def dance(self):
        print('跳舞跳舞')

class Person1(God):   #Person1类继承父类God
    pass
#创建对象 Person1类实例化对象p
p = Person1()
p.sing()
p.dance()
print('\n')



#新式类与旧式类（经典类）

#在python3 中类的定义
'''
1.方法一              #推荐使用
class Person(object):
    pass

2.方法二
class Person():
    pass

3.方法三
class Person:
    pass
'''

#在python2.x中，默认都是经典类，只有显示继承了object才是新式类。
'''
object 是python为所有对象提供的基类。
'''



#单继承
class Person2:
    Sname = '动物类'
    def __init__(self,name,sex,age):
        self.name = name
        self.sex  = sex
        self.age  = age

    def eat(self):
        print(f'{self.name}在吃东西，性别是{self.sex}，年龄是{self.age}')
#定义子类
class Lucy(Person2):
    pass
#创建对象
p1 = Lucy('Lucy','F',18)
p1.eat()
print('\n')


#继承的传递性

#爷爷类
class Animal:
    def __init__(self,name):
        self.name = name
    def eat(self):
        print('--吃--')
    def sleep(self):
        print('--睡--')
#爸爸类
class Dog(Animal):
    def bark(self):
        print(f'{self.name}在汪汪叫！')
#儿子类
class Black(Dog):
    def fly(self):
        print(f'{self.name}说：我会飞！')

#创建对象
black = Black('小黑')
black.fly()           #小黑说：我会飞！
black.bark()          #小黑在汪汪叫！
black.eat()           #--吃--
print('\n')




#继承重写

#应用场景：
'''
当父类的方法不能满足子类需求时，可以对方法进行重写。
1.覆盖父类的方法：在子类中定义一个和父类同名的方法来实现。
2.对父类方法进行扩展：在子类中重写父类方法，super().父类方法。

'''
#重写
#1.覆盖重写
class Human(object):
    def __init__(self,name):    #初始化设置
        self.name = name

    def eat(self):
        print('%s在吃饭'%self.name)

class zs(Human):           #继承
    def eat(self):         #重写--在子类中定义一个与父类同名的方法。
        print('%s在慢慢地吃饭'%self.name)

#创建对象
p3 = zs('阿四')
p3.eat()
print('\n')


#2.扩展父类
'''
调用格式一：父类名.方法名(self)

调用格式二：super().方法名()

'''
#1)扩展父类：父类名.方法名(self)

class Animal2(object):
    def eat(self):
        print('吃东西')

class Dog(Animal2):         #Dog类继承父类Animal2
    def eat(self):
        Animal2.eat(self)   #父类名.方法名(self)，用父类名调用直接扩展父类内容。
        print('啃骨头')
#对子类创建一个black对象
black = Dog()
black.eat()
print('\n')


#2)扩展父类：super().父类方法名()
class Animal3(object):
    def __init__(self,name):
        self.name = name

    def bark(self):
        print('%s在叫'%self.name)
        print('哈哈哈')
#子类
class Dog(Animal3):          #继承
    def bark(self):          #对父类进行重写
        super().bark()       #表示调用父类的方法
        print('%s在汪汪叫！'%self.name)

#创建对象
white = Dog('小白')
white.bark()
print('\n')

        
#扩展父类的应用场景
#继承父类构造方法，并进行改写
#父类
class A:
    def __init__(self,name):
        self.name = name
        print('父类中的名字是',self.name)

    def test(self):
        print('父类中的%s在哈哈笑'% self.name)

#子类
class A2(A):
    def __init__(self,name):
        super().__init__(name)   #调用父类的__init__()方法，对父类进行扩写（保留父类中的内容）
        self.name = name
        print('子类中的名字是',self.name)

    def test(self):          #对父类进行重写（覆盖改写）
        print('子类中的%s在嘻嘻笑'% self.name)

#创建子类对象
a2 = A2('Lucy')
a2.test()

        
    
